package com.gitee.apanlh.util.encode;

import com.gitee.apanlh.util.base.Empty;

/**	
 * 	16进制工具类
 * 
 * 	@author Pan
 */
public class HexUtils {
	
	/** 十六进制字符 */
	static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
	static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
	/** 十六进制字符串 */
	static final String[] HEX_STR_ARR = {"0", "1", "2", "3", "4", "5" ,"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
	static final String HEX_DIGITS = "0123456789ABCDF";
	
	/** 缓存十六进制字符转化为数字的结果 **/
	private static final int[] HEX_CACHE = new int[128];
	
	static {
	    for (int i = 0; i < HEX_CACHE.length; i++) {
	    	HEX_CACHE[i] = -1;
	    }
	    for (int i = '0'; i <= '9'; i++) {
	    	HEX_CACHE[i] = i - '0';
	    }
	    for (int i = 'A'; i <= 'F'; i++) {
	    	HEX_CACHE[i] = i - 'A' + 10;
	    }
	    for (int i = 'a'; i <= 'f'; i++) {
	    	HEX_CACHE[i] = i - 'a' + 10;
	    }
	}
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private HexUtils() {
		//	不允许外部实例
		super();
	}
	
	/**	
	 * 	int 转换16进制
	 * 	
	 * 	@author Pan
	 * 	@param  value	值
	 * 	@return	String
	 */
	public static String encode(char value) {
		return Integer.toHexString(value);
	}
	
	/**	
	 * 	int 转换16进制
	 * 	
	 * 	@author Pan
	 * 	@param  value	值
	 * 	@return	String
	 */
	public static String encode(Integer value) {
		return Integer.toHexString(value);
	}
	
	/**	
	 * 	Long 转换16进制
	 * 	
	 * 	@author Pan
	 * 	@param  value	值
	 * 	@return	String
	 */
	public static String encode(Long value) {
		return Long.toHexString(value);
	}
	
	/**	
	 *  String 转换16进制
	 *  <br>默认小写
	 *  	
	 * 	@param  content	内容
	 * 	@return	String
	 */
	public static String encode(String content) {
		return encode(content, true);
	}
	
	/**	
	 *  String 转换16进制
	 *  <br>转换后的大小写自定义
	 *  	
	 *  @author Pan
	 * 	@param  content	内容
	 * 	@param  toLowerCase true为小写, false为大写
	 * 	@return	String
	 */
	public static String encode(String content, boolean toLowerCase) {
		return encode(StrEncodeUtils.utf8EncodeToBytes(content), toLowerCase);
	}
	
	/**	
	 * 	byte[]转换16进制
	 * 		
	 * 	@author Pan
	 * 	@param  content	内容
	 * 	@return	String
	 */
	public static String encode(byte[] content) {
		return encode(content, true);
	}

	/**	
	 * 	byte[]转换16进制 
	 * 	<br>转换后的大小写自定义
	 * 	
	 * 	@author Pan
	 * 	@param  content	内容
	 * 	@param  toLowerCase true为小写, false为大写
	 * 	@return	String
	 */
	public static String encode(byte[] content, boolean toLowerCase) {
		char[] encode = encodeToChar(content, toLowerCase);
		return StrEncodeUtils.utf8EncodeToStr(new String(encode));
	}

	/**
	 * 	byte[] 转换16进制
	 * 	
	 * 	@author Pan
	 * 	@param  content	内容
	 * 	@return	char[]
	 */
	public static char[] encodeToChar(byte[] content) {
		return encodeToChar(content, false);
	}

	/**	
	 * 	byte[] 转换16进制
	 * 	
	 * 	@author Pan
	 * 	@param  content	内容
	 * 	@param  toLowerCase	true为小写, false为大写
	 * 	@return	char[]
	 */
	public static char[] encodeToChar(byte[] content, boolean toLowerCase) {
		return encodeToChar(content, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}
	 
	/**	
	 * 	byte[] 转换16进制	
	 * 	
	 * 	@author Pan
	 * 	@param  content		内容
	 * 	@param  toDigits	指定char[]数组
	 * 	@return	char[]
	 */
	private static char[] encodeToChar(byte[] content, char[] toDigits) {
		int length = content.length;
		char[] out = new char[length << 1];
		int j = 0;
		for (int i = 0; i < length; i++) {
			out[j++] = toDigits[((0xF0 & content[i]) >>> 4)];
			out[j++] = toDigits[(0xF & content[i])];
		}
		return out;
	}
	
	/**	
	 * 	十六进制转换byte[]
	 * 
	 * 	@author Pan
	 * 	@param  content	内容
	 * 	@return	byte[]
	 */
	public static byte[] decode(String content) {
		if (content == null) {
			return Empty.arrayByte();
		}
		
		int decodeLen = content.length() / 2;
	    byte[] bs = new byte[decodeLen];
	    char[] chars = content.toCharArray();
		
	    // 使用位运算将十六进制字符转换为数字，并直接赋值给转化后的字节数组
	    for (int i = 0, len = decodeLen; i < len; i++) {
	        int high = HEX_CACHE[chars[i * 2]];
	        int low = HEX_CACHE[chars[i * 2 + 1]];
	        bs[i] = (byte) (high << 4 | low);
	    }
	    return bs;
	}
	
	/**
	 * 	十六进制转换String
	 * 	
	 * 	@author Pan
	 * 	@param  hexStr	十六进制字符串
	 * 	@return	String
	 */
	public static String decodeToStr(String hexStr) {
		return StrEncodeUtils.utf8EncodeToStr(decode(hexStr));
    }
	
	/**	
	 * 	Long 16转10
	 * 	
	 * 	@param  hexStr	十六进制字符串
	 * 	@return	Long
	 */
	public static Long decodeToLong(String hexStr) {
		return Long.decode(hexStr.indexOf("0x") == -1 ? "0x".concat(hexStr) : hexStr);
	}
}
